一、函数的定义与调用
1. 函数声明
函数声明:告诉编译器函数的名称、返回值类型和参数列表,不包含函数体。
2. 函数定义
函数定义:完整实现函数功能的代码块,包含函数体。
3. 函数调用
函数调用:在程序中使用函数名和实际参数来执行函数。
重要规则:如果函数定义在调用点之后,则必须在调用前提供函数声明。
二、形参与实参、作用域
1. 形参和实参
* 形参:在函数定义中括号内声明的变量,用于接收调用者传入的数据。
* 实参:在函数调用时传递给函数的具体值或变量。
* 关系:实参的值会被传递给对应的形参,函数内部通过操作形参来处理数据。
2. 作用域
变量的作用域分为以下两类:
* 全局变量:在所有函数外部定义的变量,在整个程序生命周期内有效,可被所有函数访问。
* 局部变量:在函数或代码块内部定义的变量,只在定义它的函数或代码块内有效。
* 易错点:当全局变量和局部变量同名时,在函数内部,局部变量会“遮蔽”全局变量。
三、C++指针类型的概念及基本应用
1. 指针的本质
指针的本质:一个变量,用来保存内存地址。
2. 指针的定义与初始化
语法:类型 *指针名;
3. 两个指针相关运算符
运算符 名称 作用 示例 & 取地址 得变量的地址 int* p = &a * 解引用 得地址里的值 cout << *a;
4. 指针做函数形参
指针做函数形参可以修改指向变量的值。
5. 指针和数组
1. 数组名就是首元素地址
结论:除 sizeof 与取地址 & 外,数组名会自动退化为指向首元素的指针。
2. 指针遍历数组
结论:利用“指针 + 整数”做指针算术,可逐个访问元素。
3. 下标运算符 [] 的指针本质
结论:p[i] 等价于 *(p + i)。
4. 指针形参接收数组
结论:函数形参写成 int arr[] 或 int* arr 完全等价,传的是地址。
四、函数参数传递的概念(C++值传递、引用传递、指针传递)
1. 三种参数传递
* 参数传递方式(核心考点)
这是四级考试的重点,必须清晰区分三种方式:
传递方式 语法 是否修改原变量 特点 应用场景 值传递 void func(int x) 否 将实参的值复制一份给形参,函数内对形参的修改不影响实参。 当函数不需要修改外部变量时,安全简单。 引用传递 void func(int &x) 是 形参是实参的别名,对形参的任何操作都等同于对实参操作。效率高,无需复制。 当函数需要修改外部变量,或传递大型对象避免复制开销时。 指针传递 void func(int *x) 是 将实参的内存地址传递给形参,通过解引用指针 (*x) 来访问和修改实参的值。 常用于动态内存管理、数组操作或需要传递“可选”参数(可传空指针)。
五、C++结构体
1. 结构体类型定义
典型示例:
变量定义与初始化(3 种写法)
a) 先定义类型再定义变量:
b) 一次性定义:
c) C++11 列表初始化:
2. 访问成员(“点”与“箭头”)
1. 普通变量用 .
2. 结构体指针用 ->
3. 结构体数组
4. 结构体指针
六、C++二维数组与多维数组基本应用
1. 二维数组的定义及初始化
考点 语法示例 说明 1. 定义 int a[3][4]; 3 行 4 列,共 12 个 int,行优先连续存储 2. 初始化 int a[2][3]={{1,2,3},{4,5,6}}; 内层 {} 可省,但建议保留可读性 3. 下标访问 a[i][j] 先行后列,i∈[0,行-1],j∈[0,列-1] 4. 遍历模板 for(i) for(j) 双重循环 5. 形参 void f(int a[][4], int n) 列数必须写死,行数可省 6. 多维扩展 int b[2][3][4]; 三维同理,三层循环即可
2. 二维数组常见简单应用
1. 矩阵输入 + 求和
2. 矩阵转置(行列互换)
3. 多维数组不同位置相差字节计算
例 1:二维数组
求 &a[2][3] 与 &a[4][1] 相差多少字节?
1. 计算元素差:
行差 = 4-2 = 2 行
列差 = 1-3 = -2 列
总元素差 = 2×8 + (-2) = 14 //乘以8是因为int a[5][8]有8列
2. 字节差 = 14 × 4 = 56 字节 //乘以4是因为int占4字节
例 2:三维数组
求 &b[1][2][3] 与 &b[2][0][1] 相差多少字节?
//乘以(4×5)是因为int b[3][4][5]后面是4行5列
1. 元素差 = (2-1) × (4×5) + (0-2) × 5 + (1-3) = 20 - 10 - 2 = 8
2. 字节差 = 8 × 4 = 32 字节
七、算法:递推
1. 递推算法关键知识点
知识点 四级要求 1. 基本思想 从已知边界出发,按“状态转移方程”逐步推出目标解 2. 建模 4 步 ①定状态变量 ②写初始值 ③找转移方程 ④for 循环求解 3. 典型问题 斐波那契、青蛙跳台阶、杨辉三角、走格子计数 4. 数组维度 一维、二维(杨辉三角、部分背包)
2. 典型递推问题
1. 斐波那契(一维)
2. 青蛙跳台阶(每次 1 或 2 级)
3. 杨辉三角(二维递推)
4. 走格子(只能向右或向下)
八、算法:排序概念和稳定性
1. 排序知识点
编号 知识点 1 排序目的 将无序序列变成有序(升/降) 2 关键字 参与比较的那个数据项 3 稳定性定义 相等元素的原相对次序在排序后不变 4 稳定排序举例 冒泡、插入、归并 5 不稳定排序举例 选择、快速 6 内置函数 会用 sort(begin, end) 7 手写模板 冒泡/选择/插入
2. 常见排序复杂度表
(整型数组,长度 n)
算法 平均时间 最坏时间 额外空间 稳定性 冒泡 O(n²) O(n²) O(1) √ 选择 O(n²) O(n²) O(1) × 插入 O(n²) O(n²) O(1) √ 归并 O(n log n) O(n log n) O(n) √ 快速 O(n log n) O(n²) O(log n) ×
九、算法:排序算法(冒泡排序、插入排序、选择排序)
1. 三种排序的思想
算法 核心思想 平均/最坏时间 额外空间 稳定性 手写难度 冒泡 相邻逆序交换 O(n²)/O(n²) O(1) √稳定 ★☆☆ 插入 把当前元素插到已排好部分 O(n²)/O(n²) O(1) √稳定 ★★☆ 选择 每趟选最小(大)放最前 O(n²)/O(n²) O(1) ×不稳定 ★★☆
2. 三种排序模板代码
1. 冒泡(升序)
2. 插入(升序)
3. 选择(升序)
十、简单算法复杂度的估算(含多项式、指数复杂度)
1. 常见算法复杂度
级别 大O记号 典型循环形式 10⁵ 数据可否过 常数 O(1) 无循环 ✔ 线性 O(n) 单层for ✔ 平方 O(n²) 双重for 10⁴ 勉强,10⁵ ✘ 立方 O(n³) 三重for 10³ ✘ 指数 O(2ⁿ) / O(kⁿ) 递归、回溯 n>25 ✘
2. 常见代码时间复杂度
1. 单层循环
2. 并列循环相加取最大
3. 嵌套循环相乘
4. 指数递归
3. 常见实例时间复杂度
代码片段 复杂度 单层for累加 O(n) 冒泡排序 O(n²) 三重循环暴力 O(n³) 简单递归求斐波那契 O(2ⁿ)
十一、文件重定向与文件读写操作
1. 文件重定向和文件读写的概念
编号 名词 解析 对应工具 1 文件重定向 让cin/cout不再读写键盘屏幕,而是读写文件 freopen 2 文件读写 用ifstream/ofstream像cin/cout一样读写文件 ifstream/ofstream
2. 文件重定向和文件读写代码
1. 文件重定向(最简单,一行搞定)
说明:
* "r" 读,"w" 写;文件名用英文半角引号。
* 程序运行后,会在可执行文件同目录下出现 output.txt。
2. 文件读写(用 ifstream/ofstream,等价于 cin/cout)
3. 同时读写多组数据(循环模板)
3. 与CIN和COUT的对比
1. 设备对照表
方式 从哪读 写到哪 程序里怎么写 cin/cout默认 键盘 屏幕 cin >> x; cout << x; freopen重定向 文件 文件 freopen("in.txt","r",stdin); cin >> x; ifstream/ofstream 文件 文件 ifstream fin("in.txt"); fin >> x;
2. 语法对照表(同样读一个整数)
写法 需要头文件 读入语句 输出语句 键盘/屏幕 #include <iostream> std::cin >> x; std::cout << x; freopen #include <cstdio> 同上,cin自动改道 同上,cout自动改道 独立流 #include <fstream> std::ifstream fin("in.txt"); <br> fin >> x; std::ofstream fout("out.txt"); <br> fout << x;
十二、异常处理
1. 异常处理基本知识点
编号 名词 用通俗话说 1 异常 程序运行时出现的“意外”,如5/0、数组越界 2 try块 把可能出错的语句包裹起来 3 catch块 抓到异常后怎么处理 4 throw 手动抛出异常 5 标准异常类 std::runtime_error 等 6 头文件 #include <iostream> 已够用(少量编译器需 <stdexcept>)
2. 异常处理简单模板
1. 防止除零
2. 防止数组越界(手动抛)
3. 通用万能 catch(兜底)
4. 多个catch